package net.tarine.gastronomi.client.forms;

import java.util.List;

import net.tarine.gastronomi.client.AuthSingleton;
import net.tarine.gastronomi.client.IAuthenticatedWidget;
import net.tarine.gastronomi.client.ParamMap;
import net.tarine.gastronomi.client.UiSingleton;
import net.tarine.gastronomi.client.WaitSingleton;
import net.tarine.gastronomi.client.services.ForumService;
import net.tarine.gastronomi.client.services.ForumServiceAsync;
import net.tarine.gastronomi.client.widgets.FramePanel;
import net.tarine.gastronomi.shared.AppConst;
import net.tarine.gastronomi.shared.Role;
import net.tarine.gastronomi.shared.ValidationException;
import net.tarine.gastronomi.shared.to.ForumMessageTo;
import net.tarine.gastronomi.shared.to.ForumThreadTo;
import net.tarine.gastronomi.shared.to.GasUserTo;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.TextBox;

public class ForumThreadPage extends FramePanel implements IAuthenticatedWidget {
	
	private ForumServiceAsync forumService = GWT.create(ForumService.class);
	
	private GasUserTo user = null;
	private ParamMap params = null;
	
	private FormPanel form = null;
	private ForumThreadTo item = null;
	private String itemId = null;
	private Integer offset = null;
	private Integer pageSize = null;
	
	private TextBox titleText = null;
	private MessageEditPanel messageEditPanel = null;
	private CheckBox subscriptionCheck = null;
	
	
	private AsyncCallback<ForumThreadTo> callback = new AsyncCallback<ForumThreadTo>() {
		@Override
		public void onFailure(Throwable caught) {
			UiSingleton.get().addError(caught);
			WaitSingleton.get().stop();
		}
		@Override
		public void onSuccess(ForumThreadTo result) {
			item=result;
			drawItem();
			WaitSingleton.get().stop();
		}
	};
	
	public ForumThreadPage(ParamMap params) {
		this.params=params;
		AuthSingleton.get().authorizeWidget(this);
	}
	@Override
	public void unlockWidget(GasUserTo user) {
		this.user=user;
		init();
	}
	
	private void init() {
		if ( (user.getRoleId().equals(Role.ADMIN.getId())) ||
				(user.getRoleId().equals(Role.USER.getId())) ) {
			//GasUserTo must be admin or user to view the page
			if (params == null) {
				itemId = AppConst.NEW_ITEM_ID;
			} else {
				itemId = params.getValue(AppConst.PARAM_ID);
			}
			offset = params.getIntValue(AppConst.PARAM_OFFSET);
			if (offset == null) offset = 0;
			pageSize = params.getIntValue(AppConst.PARAM_PAGESIZE);
			if (pageSize == null) pageSize = AppConst.PAGING_ROWS;
			loadItem();
		}
	}
	
	private void drawItem() {
		this.clear();
		form = new FormPanel();
		FlowPanel holder = new FlowPanel();
		//thread title
		if(item.getId() == null) {
			FlowPanel titlePanel = new FlowPanel();
			InlineHTML title = new InlineHTML("Titolo:");
			titlePanel.add(title);
			titleText = new TextBox();
			titleText.setWidth("25em");
			titlePanel.add(titleText);
			holder.add(titlePanel);
		}
		//messages
		if (item.getForumMessagesToList() != null) {
			int lastMsgToShow = offset+pageSize;
			if (lastMsgToShow > item.getForumMessagesToList().size()) lastMsgToShow = item.getForumMessagesToList().size();
			for (int i = 0; i<lastMsgToShow; i++) {
				MessageDisplayPanel mdp = new MessageDisplayPanel(item.getForumMessagesToList().get(i));
				holder.add(mdp);
			}
		}
		//new message panel
		messageEditPanel = new MessageEditPanel(item, null);
		messageEditPanel.setStyleName("message-text-area");
		holder.add(messageEditPanel);
		//Subscription
		subscriptionCheck = new CheckBox("Ricevi le risposte come email <br/>", true);
		loadSubscription();
		subscriptionCheck.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				saveThreadSubscription();
			}
		});
		holder.add(subscriptionCheck);
		//Buttons
		Button sendMessageButton = new Button("Invia messaggio");
		sendMessageButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				try {
					save();
				} catch (ValidationException e) {
					UiSingleton.get().addWarning(e.getMessage());
				}
			}
		});
		holder.add(sendMessageButton);
		
		form.add(holder);
		if (item.getTitle() != null) {
			this.set(form, item.getTitle());
		} else {
			this.set(form, "Nuova discussione");
		}
	}
	
	// Asynchoronous methods
	
	
	private void loadItem() {
		WaitSingleton.get().start();
		//if it's not loaded then call the server
		if (itemId.equals(AppConst.NEW_ITEM_ID)) {
			String gasId = UiSingleton.get().getGas().getId();
			forumService.createForumThread(gasId, callback);
		} else {
			forumService.findForumThreadById(itemId, callback);
		}
	}
	
	private void save() throws ValidationException {
		WaitSingleton.get().start();
		//validation
		if (item.getId() == null) {
			if (titleText.getValue() == null) throw new ValidationException("Il titolo non puo' essere vuoto");
			if (titleText.getValue().length() < 2) throw new ValidationException("Il titolo non puo' essere vuoto");
		}
		ForumMessageTo newMessage = messageEditPanel.getForumMessage();
		if (newMessage.getText() == null) throw new ValidationException("Il messaggio non puo' essere vuoto");
		if (newMessage.getText().length() < 2) throw new ValidationException("Il messaggio non puo' essere vuoto");
		//fill pojos with data
		if (item.getId() == null) {
			item.setTitle(titleText.getValue());
			item.setGasUserTo(user);
		}
		saveThreadSubscription();
		forumService.addForumThreadMessage(item, newMessage, callback);
	}
	
	private void loadSubscription() {
		AsyncCallback<List<String>> callback = new AsyncCallback<List<String>>() {
			@Override
			public void onFailure(Throwable caught) {
				UiSingleton.get().addError(caught);
			}
			@Override
			public void onSuccess(List<String> result) {
				subscriptionCheck.setValue(false);
				for (String gasUserId:result) {
					if (user.getId().equals(gasUserId)) {
						subscriptionCheck.setValue(true);
						break;
					}
				}
			}
		};
		if (itemId.equals(AppConst.NEW_ITEM_ID+"")) {
			subscriptionCheck.setValue(user.getReceiveForumEmail());
		} else {
			forumService.findThreadSubscriberIds(itemId, callback);
		}
	}
	
	private void saveThreadSubscription() {
		AsyncCallback<Boolean> subscriptionCallback = new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
				UiSingleton.get().addError(caught);
			}
			@Override
			public void onSuccess(Boolean result) {
				subscriptionCheck.setValue(result);
			}
		};
		if (item.getId() != null) {
			forumService.subscribeThread(item.getId(), user.getId(), subscriptionCheck.getValue(), subscriptionCallback);
		}
	}
}
